; LBA-48 MBR by Anthony Q. Bachler copyright 2009, released under the GPL v3

section .text 

[bits 16]
	jmp 0x07c0:start
start:
	; move MBR to 0x0600:0x0000
	mov ax , 0x0600
	mov ds , ax
	mov ax , 0x07c0
	mov es , ax
	xor si , si
	xor di , di
	mov cx , 0x0200
	movsb
	rep
	
	; jump to the moved MBR
	jmp 0x0600:begin
	
begin:
	; reset the segment registers
	mov ax , 0x0600
	mov ds , ax
	
	; find the first bootable partition
	mov ax , partition_0_lo
find_boot:
	mov di , ax
	mov dl , [ds:di]
	cmp dl , 0x80
	je load_boot						; found it
	add ax , 0x0010
	cmp ax , partition_0_lo+64
	jne find_boot
	
	; error, no bootable partition
	hlt
	
load_boot:
	mov [boot_partition] , ax			; save the active partition
	
	; check for LBA BIOS extensions
	mov ah , 0x41
	mov bx , 0x55aa
	mov dl , 0x80
	int 0x13
	jnc lba_available
	
	; LBA BIOS support is not present use CHS
read_chs_sector:
	mov ax , 0x0201
	mov cx , [ds:di+2]		; load Cylinder and Sector
	mov dh , [ds:di+1]		; load Head
	mov dl , 0x80
	xor bx , bx
	int 0x13
	jc read_chs_sector
	jmp 0x07c0:0x0000
	
lba_available:
	mov eax , [lba_64_signature]
	cmp eax , 0x02200808
	je lba_64_available
	
lba_32_available:
	mov ax , 0x0600						; set the segment
	mov ds , ax							; set the data segment
	mov es , ax							; set the extra segment
	mov ax , [boot_partition]			; get the ptr to the partition
	add ax , 0x0008						; offset 8 is the relative start sector (LBA)
	mov si , ax							; set the source
	mov ax , block_start				; set the destination
	mov di , ax
	mov cx , 0x0004						; copy 4 bytes for LBA-32
	movsb
	rep
	
	mov ax , 0x0001						; set the number of sectors to copy
	mov [transfer_size] , ax
	mov dl , 0x80						; set the drive number
	mov ax , packet						; ptr to the packet
	mov si , ax
	mov ah , 0x42						; int 0x13 subfunction 0x42 Read LBA sector(s)
	int 0x13
	
	jc lba_32_available					; if there is an error retry
	jmp 0x07c0:0x0000					; jump to the partition boot sector

lba_64_available:

	;jmp lba_32_available				; temp while under development
	
	mov ax , 0x0600						; set the segment
	mov ds , ax							; set the data segment
	mov es , ax							; set the extra segment
	mov ax , [boot_partition-(partition_0_lo-partition_0_hi)]			; get the ptr to the partition
	mov si , ax							; set the source
	mov ax , block_start				; set the destination
	mov di , ax
	mov cx , 0x0006						; copy 6 bytes for LBA-48
	movsb
	rep
	
	mov ax , 0x0001						; set the number of sectors to copy
	mov [transfer_size] , ax
	mov dl , 0x80						; set the drive number
	mov ax , packet						; ptr to the packet
	mov si , ax
	mov ah , 0x42						; int 0x13 subfunction 0x42 Read LBA sector(s)
	int 0x13
	
	jc lba_64_available					; if there is an error retry
	jmp 0x07c0:0x0000					; jump to the partition boot sector

boot_partition	dw 0x0000							; ptr to the active partition entry
packet			db 0x10								; size of packet	
				db 0x00								; reserved
transfer_size	dw 0x0001							; number of blocks to transfer 
transfer_buffer	dw 0x07c0 , 0x0000					; destination buffer
block_start		db 0x01 , 0x00 , 0x00 , 0x00		; LBA block to load
				db 0x00 , 0x00 , 0x00 , 0x00
	times 368-($-$$) db 0

	
	; LBA-64 extended fields
partition_0_hi:
	times 16 db 0xff
partition_1_hi:
	times 16 db 0xff
partition_2_hi:
	times 16 db 0xff
partition_3_hi:
	times 16 db 0xff
lba_64_signature:
	db 0x08 , 0x08
	db 0x20 , 0x02

drive_id:	
	db 0xff , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x09 ; Optional "unique" disk ID
	
partition_0_lo:
	times 16 db 0
partition_1_lo:
	times 16 db 0
partition_2_lo:
	times 16 db 0
partition_3_lo:
	times 16 db 0
	
	db 0x55
	db 0xAA
   
   
section .data 

    ; put data items here

	
section .bss 

        ; put uninitialised data here






